#pragma once

#include <Scanner/token.h>
#include <string>
#include <unordered_map>
#include <functional>

// Scanner不同于Lexer
// 1. Lexer一次性分析完整段输入；而Scanner每次只分析一个Token，
// 当Compiler要求下一个Token时，才会步进
class Scanner
{
public:
	Scanner();
	void initScanner(std::string_view source, int line);
	Token scanToken();

	static std::unordered_map<std::string_view, TokenType> reservedKeywords;

private:
	std::string_view source;
	int line;	   // 记录当前行
	int lineStart; // 记录当前行的起始位置（\n之后第一个字符）
	int offset;	   // source[offset]

	int tokenOffset; // 一个Token的起始下标
	int tokenLine;	 // token所在行
	int tokenColumn; // token起始列标

private:
	char advance();	 // 获取将要分词的字符并前进
	char peek();	 // 获取将要分析的字符
	char peekNext(); // 获取下下个要分析的字符
	bool isAtEnd() const;
	bool match(char expected);
	void advanceWhile(const std::function<bool(int)> &checker);
	bool advanceTo(char expected);

	std::string_view lexeme();
	Token makeToken(TokenType type);
	Token makeString();
	Token makeNumber();
	Token makeIdentifier();
	Token eofToken();
	Token errorToken(std::string_view message);
};